package com.atguigu.tingshu.album.listener;

import com.alibaba.fastjson.JSON;
import com.atguigu.tingshu.album.mapper.AlbumAttributeValueMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.common.constant.RabbitConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.model.album.AlbumAttributeValue;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.vo.album.TrackStatMqVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.rabbitmq.client.Channel;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
public class TrackListener {

    @Autowired
    private TrackStatMapper trackStatMapper;

    @Autowired
    private AlbumStatMapper albumStatMapper;

    @Autowired
    private AlbumAttributeValueMapper albumAttributeValueMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(RabbitConstant.TRACK_STAT_QUEUE),
            exchange = @Exchange(value = RabbitConstant.USER_EXCHANGE, type = ExchangeTypes.TOPIC, ignoreDeclarationExceptions = "true"),
            key = RabbitConstant.TRACK_STAT_RK
    ))
    public void trackStat(String msg, Channel channel, Message message) throws IOException {
        if (StringUtils.isBlank(msg)){
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            return ;
        }

        // 反序列化
        TrackStatMqVo statMqVo = JSON.parseObject(msg, TrackStatMqVo.class);
        if (statMqVo == null){
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }
        // 获取消息中的参数
        String businessNo = statMqVo.getBusinessNo();
        Long trackId = statMqVo.getTrackId();
        String statType = statMqVo.getStatType();
        Long albumId = statMqVo.getAlbumId();
        Integer count = statMqVo.getCount();
        // 获取消息中的参数，如果任何一个参数为空则为垃圾消息
        if (StringUtils.isBlank(businessNo) || albumId == null || trackId == null
                || StringUtils.isBlank(statType) || count == null || count <= 0){
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            return;
        }

        // 查询对应声音的统计信息，进行统计的累加
        TrackStat trackStat = this.trackStatMapper.selectOne(new LambdaQueryWrapper<TrackStat>()
                .eq(TrackStat::getTrackId, trackId).eq(TrackStat::getStatType, statType));
        // 创建声音的时候，就已经初始化了统计信息，所以声音的对应统计信息时不为空
        trackStat.setStatNum(trackStat.getStatNum() + count);
        this.trackStatMapper.updateById(trackStat);

        // 对应专辑的统计信息，也要跟着进行更新：播放量 评论数
        String albumStatType = SystemConstant.ALBUM_STAT_PLAY;
        switch (statType){
            case SystemConstant.TRACK_STAT_PLAY:
                break;
            case SystemConstant.TRACK_STAT_COMMENT:
                albumStatType = SystemConstant.ALBUM_STAT_COMMENT;
                break;
        }
        AlbumStat albumStat = this.albumStatMapper.selectOne(new LambdaQueryWrapper<AlbumStat>()
                .eq(AlbumStat::getAlbumId, albumId).eq(AlbumStat::getStatType, albumStatType));
        albumStat.setStatNum(albumStat.getStatNum() + count);
        this.albumStatMapper.updateById(albumStat);

        // 确认掉消息
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }

    //同步到消息Redis中
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(RabbitConstant.ALBUM_REDIS_SAVE_QUEUE),
            exchange = @Exchange(value = RabbitConstant.MXW_EXCHANGE, type = ExchangeTypes.TOPIC, ignoreDeclarationExceptions = "true"),
            key = RabbitConstant.MXW_ALBUM_RK
    ))
    public void syncDataToRedis(String json,Channel channel,Message message) throws IOException{
        if (StringUtils.isBlank(json)){
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            return ;
        }
        // 反序列化
        MxwObject mxwObject = JSON.parseObject(json, MxwObject.class);
        if (mxwObject.getTable().equals("album_info")){
            // 把data反序列化为albumInfo对象
            AlbumInfo albumInfo = JSON.parseObject(mxwObject.getData(), AlbumInfo.class);
            if (mxwObject.getType().equals("insert") || mxwObject.getType().equals("update")){
                // 把专辑对应标签信息查询出来
                List<AlbumAttributeValue> albumAttributeValues = this.albumAttributeValueMapper.selectList(new LambdaQueryWrapper<AlbumAttributeValue>().eq(AlbumAttributeValue::getAlbumId, albumInfo.getId()));
                albumInfo.setAlbumAttributeValueVoList(albumAttributeValues);
                // 同步到redis
                this.redisTemplate.opsForValue().set(RedisConstant.ALBUM_INFO_PREFIX + albumInfo.getId(), albumInfo, RedisConstant.ALBUM_TIMEOUT, TimeUnit.SECONDS);
            } else if (mxwObject.getType().equals("delete")) {
                // 删除redis对应的缓存
                this.redisTemplate.delete(RedisConstant.ALBUM_INFO_PREFIX + albumInfo.getId());
            }
        } else if (mxwObject.getTable().equals("track_info")) {
            // TODO:
        } else if (mxwObject.getTable().equals("base_category1") || mxwObject.getTable().equals("base_category2") || mxwObject.getTable().equals("base_category2")) {
            // TODO: 同步三级分类的缓存 base_category_view
        }

        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }
}
